﻿Imports PTIC_GestionBDD
Imports PTIC_Util
Imports PTIC_Util.gestionCalculs
Imports Actuariat.comptes
Imports Actuariat

Namespace moteurTauxGaranti1

#Region "Classes générales Calcul individuel / Résultats"
    Public MustInherit Class CalculAutonomeMoteur1
        Inherits gestionCalculs.CalculIndividuel
        Protected _moteur As Moteur_Methode1
        Public Sub New(ByVal moteur As Moteur_Methode1)
            MyBase.New()
            _moteur = moteur
            _resultats = New resultatsMoteur1()
        End Sub
        Public Overloads ReadOnly Property resultats() As resultatsMoteur1
            Get
                Return _resultats
            End Get
        End Property
    End Class
    Public Class resultatsMoteur1
        Dim _PPurePf As Double
        Dim _PTechPf As Double
        Dim _sommeCSR As Double
        Public Property PPurePf() As Double
            Get
                Return _PPurePf
            End Get
            Set(ByVal value As Double)
                _PPurePf = value
            End Set
        End Property
        Public Property PTechPf() As Double
            Get
                Return _PTechPf
            End Get
            Set(ByVal value As Double)
                _PTechPf = value
            End Set
        End Property
        Public Property sommeCSR() As Double
            Get
                Return _sommeCSR
            End Get
            Set(ByVal value As Double)
                _sommeCSR = value
            End Set
        End Property
    End Class
#End Region

#Region "Simulations"
    Public MustInherit Class simulationIndividuelle
        Inherits CalculAutonomeMoteur1

        Protected _nom As String
        Protected _chocMin As Double
        Protected _chocMax As Double
        Protected _pas As Double
        Protected _chocRadar As Double
        Protected _valeurRadar As Double

        Public Sub New(ByVal moteur As Moteur_Methode1, _
                       ByVal nom As String, _
                       ByVal chocMin As Double, _
                       ByVal chocMax As Double, _
                       ByVal pas As Double, _
                       ByVal chocRadar As Double)
            MyBase.New(moteur)
            _nom = nom
            _chocMin = chocMin
            _chocMax = chocMax
            _pas = pas
            _chocRadar = chocRadar
            _resultats = New DataTable
            _resultats.Columns.Add(_nom, Type.GetType("System.Double"))
            _resultats.Columns.Add("S/P", Type.GetType("System.Double"))
        End Sub
        Public Overloads ReadOnly Property resultats() As DataTable
            Get
                Return _resultats
            End Get
        End Property
        Public ReadOnly Property chocRadar() As Double
            Get
                Return _chocRadar
            End Get
        End Property
        Public ReadOnly Property valeurRadar() As Double
            Get
                Return _valeurRadar
            End Get
        End Property
    End Class
    Public Class simulationSensibiliteParametre
        Inherits simulationIndividuelle
        Public Sub New(ByVal moteur As Moteur_Methode1, _
                       ByVal nomParametre As String, _
                       ByVal chocMin As Double, _
                       ByVal chocMax As Double, _
                       ByVal pas As Double, _
                       ByVal chocRadar As Double)
            MyBase.New(moteur, nomParametre, chocMin, chocMax, pas, chocRadar)
        End Sub
        Protected Overrides Sub procedureCalcul()
            Dim val As Double = _chocMin
            Dim rowEnCours As DataRow
            CType(_resultats, DataTable).Clear()
            'La sensibilité
            While val <= _chocMax
                rowEnCours = _resultats.NewRow
                _moteur.listeParametres(_nom).setSimulDouble(val)
                _moteur.calcule(False)
                rowEnCours(_nom) = val
                rowEnCours("S/P") = _moteur.PPurePf / _moteur.PTechPf
                _resultats.Rows.Add(rowEnCours)
                val = val + _pas
            End While
            'Le choc pour le radar
            _moteur.listeParametres(_nom).setSimulDouble(_chocRadar)
            _moteur.calcule(False)
            _valeurRadar = _moteur.PPurePf / _moteur.PTechPf
            _moteur.listeParametres(_nom).setSimulDouble(0)
        End Sub
    End Class
    Public Class simulationStressTestCSR
        Inherits simulationIndividuelle
        Public Sub New(ByVal moteur1 As Moteur_Methode1, _
                       ByVal nom As String, _
                       ByVal chocMin As Double, _
                       ByVal chocMax As Double, _
                       ByVal pas As Double, _
                       ByVal chocRadar As Double)
            MyBase.New(moteur1, nom, chocMin, chocMax, pas, chocRadar)
        End Sub
        Protected Overrides Sub procedureCalcul()

            Dim val As Double = _chocMin, sumCSR_scenCentral(_moteur.tableTravail.Rows.Count - 1) As Double
            CType(_resultats, DataTable).Clear()

            'Sauvegarde des CSR du scénario central
            For i As Integer = 0 To _moteur.tableTravail.Rows.Count - 1
                sumCSR_scenCentral(i) = _moteur.tableTravail.Rows(i)(nomSumCSR)
            Next

            Dim rowEnCours As DataRow

            'La sensibilité
            While val <= _chocMax
                rowEnCours = _resultats.NewRow
                'Retraiter la table en entrée
                For i As Integer = 0 To _moteur.tableTravail.Rows.Count - 1
                    If _moteur.tableTravail.Rows(i)("id_type_pret") = "Immobilier" Then
                        _moteur.tableTravail.Rows(i)(nomSumCSR) = sumCSR_scenCentral(i) * (1 + val)
                    End If
                Next
                _moteur.calcule(False)
                rowEnCours("ST_Immo") = val
                rowEnCours("S/P") = _moteur.PPurePf / _moteur.PTechPf
                _resultats.Rows.Add(rowEnCours)
                val = val + _pas
            End While

            'Le radar
            For i As Integer = 0 To _moteur.tableTravail.Rows.Count - 1
                If _moteur.tableTravail.Rows(i)("id_type_pret") = "Immobilier" Then
                    _moteur.tableTravail.Rows(i)(nomSumCSR) = sumCSR_scenCentral(i) * (1 + _chocRadar)
                End If
            Next
            _moteur.calcule(False)
            _valeurRadar = _moteur.PPurePf / _moteur.PTechPf

            'Rétablissement des valeurs des CSR du scénario central
            For i As Integer = 0 To _moteur.tableTravail.Rows.Count - 1
                If _moteur.tableTravail.Rows(i)("id_type_pret") = "Immobilier" Then
                    _moteur.tableTravail.Rows(i)(nomSumCSR) = sumCSR_scenCentral(i)
                End If
            Next

        End Sub
    End Class
    Public Class simulationStressTestTrAge
        Inherits simulationIndividuelle
        Public Sub New(ByVal moteur1 As Moteur_Methode1, _
                       ByVal nom As String, _
                       ByVal chocMin As Double, _
                       ByVal chocMax As Double, _
                       ByVal pas As Double, _
                       ByVal chocRadar As Double)
            MyBase.New(moteur1, nom, chocMin, chocMax, pas, chocRadar)
        End Sub
        Protected Overrides Sub procedureCalcul()

            Dim val As Double = _chocMin, sumCSR_scenCentral(_moteur.tableTravail.Rows.Count - 1) As Double
            CType(_resultats, DataTable).Clear()

            'Sauvegarde des CSR du scénario central
            For i As Integer = 0 To _moteur.tableTravail.Rows.Count - 1
                sumCSR_scenCentral(i) = _moteur.tableTravail.Rows(i)(nomSumCSR)
            Next

            Dim rowEnCours As DataRow

            'La sensibilité
            While val <= _chocMax
                rowEnCours = _resultats.NewRow
                'Retraiter la table en entrée
                For i As Integer = 0 To _moteur.tableTravail.Rows.Count - 1
                    If _moteur.tableTravail.Rows(i)(nomtrAge) = "C" Then
                        _moteur.tableTravail.Rows(i)(nomSumCSR) = sumCSR_scenCentral(i) * (1 + val)
                    End If
                Next
                _moteur.calcule(False)
                rowEnCours("ST_Tr_age") = val
                rowEnCours("S/P") = _moteur.PPurePf / _moteur.PTechPf
                _resultats.Rows.Add(rowEnCours)
                val = val + _pas
            End While

            'Le radar
            For i As Integer = 0 To _moteur.tableTravail.Rows.Count - 1
                If _moteur.tableTravail.Rows(i)(nomtrAge) = "C" Then
                    _moteur.tableTravail.Rows(i)(nomSumCSR) = sumCSR_scenCentral(i) * (1 + _chocRadar)
                End If
            Next
            _moteur.calcule(False)
            _valeurRadar = _moteur.PPurePf / _moteur.PTechPf

            For i As Integer = 0 To _moteur.tableTravail.Rows.Count - 1
                If _moteur.tableTravail.Rows(i)(nomtrAge) = "C" Then
                    _moteur.tableTravail.Rows(i)(nomSumCSR) = sumCSR_scenCentral(i)
                End If
            Next

        End Sub
    End Class
    Public Class simulationsMoteur1
        Inherits CalculRacine

        Protected _moteur As Moteur_Methode1
        Protected _radar As Dictionary(Of String, Double)

        'Ajouter la gestion des recalculs et la rendre accessible depuis l'extérieur
        'La classe simulationMoteur1 contient une fonction de calcul, qui elle même contient plusieurs
        'fonctions de calcul (la fonction de calcul est de type Englobante)
        Friend Sub New(ByVal moteur As Moteur_Methode1, ByVal etatCalcul As etatCalcul)
            _moteur = moteur
            defaut()
        End Sub
        Public Sub New(ByVal moteur As Moteur_Methode1)
            _moteur = moteur
            defaut()
        End Sub
        Public Sub defaut()
            AjouteFonctionCalculIntermediaire(New simulationSensibiliteParametre(_moteur, nomTx_TechA, -0.02, 0.02, 0.004, 0.01))
            AjouteFonctionCalculIntermediaire(New simulationSensibiliteParametre(_moteur, nomDuree_Actu, -24, 24, 4, 12))
            AjouteFonctionCalculIntermediaire(New simulationSensibiliteParametre(_moteur, nomTxNom_Actu, -0.02, 0.02, 0.004, 0.01))
            AjouteFonctionCalculIntermediaire(New simulationSensibiliteParametre(_moteur, nomTx_CommiContA, -0.2, 0.2, 0.04, 0.01))
            AjouteFonctionCalculIntermediaire(New simulationSensibiliteParametre(_moteur, nomTx_fraiGestA, -0.05, 0.05, 0.01, 0.01))
            AjouteFonctionCalculIntermediaire(New simulationStressTestCSR(_moteur, "ST_Immo", -0.5, 0.5, 0.1, 0.1))
            AjouteFonctionCalculIntermediaire(New simulationStressTestTrAge(_moteur, "ST_Tr_age", -0.5, 0.5, 0.1, 0.1))
        End Sub

        Public Function Values() As List(Of IFonctionCalcul)
            Return ListeFonctionsCalculIntermediaires()
        End Function

        Public ReadOnly Property SimulTx_TechA() As simulationIndividuelle
            Get
                Return _lFonctionsCalculIntermediaires(0)
            End Get
        End Property
        Public ReadOnly Property SimulDuree_Actu() As simulationIndividuelle
            Get
                Return _lFonctionsCalculIntermediaires(1)
            End Get
        End Property
        Public ReadOnly Property SimulTxNom_Actu() As simulationIndividuelle
            Get
                Return _lFonctionsCalculIntermediaires(2)
            End Get
        End Property
        Public ReadOnly Property SimulTx_CommiContA() As simulationIndividuelle
            Get
                Return _lFonctionsCalculIntermediaires(3)
            End Get
        End Property
        Public ReadOnly Property SimulTx_fraiGestA() As simulationIndividuelle
            Get
                Return _lFonctionsCalculIntermediaires(4)
            End Get
        End Property
        Public ReadOnly Property SimulST_Immo() As simulationIndividuelle
            Get
                Return _lFonctionsCalculIntermediaires(5)
            End Get
        End Property
        Public ReadOnly Property SimulST_Tr_age() As simulationIndividuelle
            Get
                Return _lFonctionsCalculIntermediaires(6)
            End Get
        End Property
        Public ReadOnly Property SimulRadar() As Dictionary(Of String, Double)
            Get
                Return _radar
            End Get
        End Property

        Public Overrides Sub Calculer()

            Dim debut, fin As Double
            debut = Environment.TickCount
            _moteur.calculeInit()

            MyBase.Calculer()

            _moteur.calculeCloture()
            MAJradar()
            'Créer un tableau synthétique à l'aide de tous les résultats correspondant aux valeurs du radar
            fin = Environment.TickCount
            MsgBox("Temps en secondes : " & (fin - debut) / 1000)

        End Sub
        Private Sub MAJradar()
            _radar = New Dictionary(Of String, Double)
            _radar.Clear()
            _radar.Add(nomTx_TechA, SimulTx_TechA.valeurRadar)
            _radar.Add(nomDuree_Actu, SimulDuree_Actu.valeurRadar)
            _radar.Add(nomTxNom_Actu, SimulTxNom_Actu.valeurRadar)
            _radar.Add(nomTx_CommiContA, SimulTx_CommiContA.valeurRadar)
            _radar.Add(nomTx_fraiGestA, SimulTx_fraiGestA.valeurRadar)
            _radar.Add("ST_Immo", SimulST_Immo.valeurRadar)
            _radar.Add("ST_Tr_age", SimulST_Tr_age.valeurRadar)
        End Sub

    End Class
#End Region

#Region "Scénario central"
    Public Class scenarioCentralMoteur1
        Inherits CalculAutonomeMoteur1
        Public Sub New(ByVal moteur As Moteur_Methode1)
            MyBase.New(moteur)
        End Sub
        Protected Overrides Sub procedureCalcul()
            If (_moteur.tableTravail.Columns.Contains("sexe_assu") And _
                _moteur.tableTravail.Columns.Contains("id_option")) <> True Then
                MsgBox("Le sexe et l'identifiant option doivent faire partie de la segmentation")
                Exit Sub
            End If
            _moteur.calculeInit()
            _moteur.calcule(True)
            _moteur.calculeCloture()
            resultats.PPurePf = _moteur.PPurePf
            resultats.PTechPf = _moteur.PTechPf
            resultats.sommeCSR = _moteur.sommeCSR
        End Sub
    End Class
#End Region

#Region "Coeur"
    Public Class Moteur_Methode1
        Inherits Traitement

#Region "Variables de classe"
        'Collection de paramètres de l'étude en cours
        Protected _coll_param As ParametresList
        'Table contenant les segments et toutes leurs caractéristiques
        Protected _tble_travail As DataTable
        'Tables de mortalité H/F, maintien INCAP/INVAL hors franchise, coefficients de réduction à appliquer à cause de la franchise
        Protected _tble_mortalite_H As DataTable, _table_mortalite_F As DataTable, _TbleINCINVTaux As DataTable
        Protected _TbleINCINVFra As DataTable
        'Résultats du calcul / Scénario central / Simulations
        Protected _resultatsCalcul As resultatsMoteur1
        Protected _scenarioCentral As scenarioCentralMoteur1
        Protected _simulations As simulationsMoteur1
#End Region

#Region "Création d'une instance"
        Public Sub New(ByVal nom As String, _
                       ByVal coll_Param As ParametresList, _
                       ByVal universBDD As UniversOMANE)
            MyBase.New(nom, universBDD)
            'Collection de paramètres afférents à l'étude en cours
            _coll_param = coll_Param
            'Objet permettant de stocker les résultats du moteur et du scénario central
            _resultatsCalcul = New resultatsMoteur1()
            _scenarioCentral = New scenarioCentralMoteur1(Me)
            _simulations = New simulationsMoteur1(Me)
            _simulations.AjouteFonctionCalculIntermediaire(_scenarioCentral)
            ajouteObsGestionRecalculs()
            ajouteObsListeParametres()
        End Sub
        Private Sub ajouteObsGestionRecalculs()
            'Placer le moteur 1 comme observateur de tous les paramètres influençant son calcul
            'Cette classe joue ici le rôle de médiateur et de façade
            _scenarioCentral.ajouteObserver(Me)
            _simulations.ajouteObserver(Me)
        End Sub
        Private Sub ajouteObsListeParametres()
            If Not _coll_param Is Nothing Then
                For Each param As baseParametre In _coll_param.Values
                    If param.methode_Cal(0) Then
                        param.ajouteObserver(Me)
                    End If
                Next
            End If
        End Sub
        Private Sub retireObsListeParametres()
            If Not _coll_param Is Nothing Then
                For Each param As baseParametre In _coll_param.Values
                    If param.methode_Cal(0) Then param.retireObserver(Me)
                Next
            End If
        End Sub
#End Region

#Region "Propriétés"
        Public Property listeParametres() As ParametresList
            Get
                Return _coll_param
            End Get
            Set(ByVal value As ParametresList)
                If Not value Is _coll_param Then
                    retireObsListeParametres()
                    _coll_param = value
                    ajouteObsListeParametres()
                    _coll_param = value
                End If
            End Set
        End Property
        Public Overrides Property nomTableDansBDD() As String
            Get
                Return _sNomTable
            End Get
            Set(ByVal value As String)
                _sNomTable = value
            End Set
        End Property
        Public ReadOnly Property etatCalculScenCentral() As valueEtatCalcul
            Get
                Return _scenarioCentral.etatCalcul
            End Get
        End Property
        Public ReadOnly Property etatCalculSimulations() As valueEtatCalcul
            Get
                Return simulations.EtatCalcul
            End Get
        End Property
        Public ReadOnly Property tableTravail() As DataTable
            Get
                Return _tble_travail
            End Get
        End Property
        Public ReadOnly Property PPurePf() As Double
            Get
                Return _resultatsCalcul.PPurePf
            End Get
        End Property
        Public ReadOnly Property PTechPf() As Double
            Get
                Return _resultatsCalcul.PTechPf
            End Get
        End Property
        Public ReadOnly Property sommeCSR() As Double
            Get
                Return _resultatsCalcul.sommeCSR
            End Get
        End Property
        Public ReadOnly Property PPure_ScenCentral() As Double
            Get
                Return _scenarioCentral.resultats.PPurePf
            End Get
        End Property
        Public ReadOnly Property PTechPf_ScenCentral() As Double
            Get
                Return _scenarioCentral.resultats.PTechPf
            End Get
        End Property
        Public ReadOnly Property ratioSP_scenCentral() As Double
            Get
                Return _scenarioCentral.resultats.PPurePf / _scenarioCentral.resultats.PTechPf
            End Get
        End Property
        Public ReadOnly Property sommeCSR_ScenCentral()
            Get
                Return _scenarioCentral.resultats.sommeCSR
            End Get
        End Property
        Public ReadOnly Property simulations() As simulationsMoteur1
            Get
                Return _simulations
            End Get
        End Property
#End Region

#Region "Gestion de la table en entrée et des tables de travail"
        'Procédure qui récupère les tables de mortalité et taux INCINV
        ''On suppose que ces tables se trouvent dans la même BDD ACCESS que la table d'encours
        'Dans la V2, ces tables sont stockées au format SAS
        Public Sub init_tbles_travail()

            Dim univOMANE As UniversOMANE = CType(_univers, UniversOMANE)
            _tble_mortalite_H = univOMANE.listeTraitements.getTraitTbleMortH.execute_DataTable(True)
            _table_mortalite_F = univOMANE.listeTraitements.getTraitTbleMortF.execute_DataTable(True)

            _TbleINCINVTaux = univOMANE.getDataTableINCINVtaux(csteNomTbleINCINVtaux)
            _TbleINCINVFra = univOMANE.getDataTableINCINVfra(csteNomTbleINCINVfra)

            _tble_travail = univOMANE.listeTraitements.getTraitEntreeModeleTxGar.execute_DataTable(True)
        End Sub
        'Public Sub recup_ExtSeg()
        'Cette méthode permet d'initialiser la table de travail, au niveau de segmentation
        'le plus fin paramétré dans l'onglet paramSeg
        '   - Exécuter la requête qui permet de créer la table des champs calculés (l'âge, etc...)
        '     (rien ne vient modifier cette requête, elle peut donc être effectuée à l'initialisation)
        '   - Exécuter la requête de liaison aux tables de travail (à refaire à chaque fois que l'une
        '     d'entre elle est modifiée) pour les Qx et le tarif
        '   - Agréger la table ainsi obtenue selon les variables de segmentation retenues en prenant soin
        '     de calculer les moyennes pondérées par les capitaux sous risque pour les variables NUMERIQUES

        'Dans la version de la présentation, les tables de mortalité et de tarif étant fixées, la table
        'de travail au niveau de granularité le plus fin est déjà préparée

        'Il reste à l'agréger au niveau de détail retenu pour la segmentation          

        'End Sub
#End Region

#Region "Calculs"

#Region "Héritage classe traitement"
        Public Overrides Function execute_DataTable(ByVal stockageBDDlocale As Boolean) As System.Data.DataTable
            Return _tble_travail
        End Function
        Public Overrides Function execute_DataTableToDgv(ByVal stockageBDDlocale As Boolean, ByVal dgv As System.Windows.Forms.DataGridView) As System.Data.DataTable
            MsgBox("La fonction execute_DataTableToDgv du moteur de calcul 1 est en cours de développement")
            Return Nothing
        End Function
        Public Overrides Function execute_BDD() As String
            'Vérifier que le traitement est à jour dans la base de données
            Return True
        End Function
#End Region

        Public Sub calculerScenarioCentral()
            _scenarioCentral.Calculer()
        End Sub
        Public Sub calculerSimulations()
            simulations.Calculer()
        End Sub

        Public Sub calculeInit()

            'Vérification que les paramètres permettant de calculer les grandeurs actuarielles sont bien à jour
            Dim tbleDureeActu As DataTable = CType(_univers, UniversOMANE).listeTraitements.getTraitRegSegmentationParamSens(nomDuree_Actu).execute_DataTable(True)
            Dim tbleTxMortActu As DataTable = CType(_univers, UniversOMANE).listeTraitements.getTraitRegSegmentationParamSens(nomTxMort_Actu).execute_DataTable(True)
            Dim tbleTxNomActu As DataTable = CType(_univers, UniversOMANE).listeTraitements.getTraitRegSegmentationParamSens(nomTxNom_Actu).execute_DataTable(True)
            'Mise à jour des valeurs des paramètres en fonction des extractions
            _coll_param.Duree_Actu.setValeursDataTable(tbleDureeActu)
            _coll_param.TxMort_Actu.setValeursDataTable(tbleTxMortActu)
            _coll_param.TxNom_Actu.setValeursDataTable(tbleTxNomActu)

            _coll_param.MAJ_CollParamDeclUniq(1)
            Dim parametres_decl As Hashtable = _coll_param.getParamDecl
            Dim parametres_uniq As Hashtable = _coll_param.getParamUniq

            'Mise à jour des valeurs en cours de tous les paramètres uniques
            For Each p As IParamV2 In parametres_uniq.Values
                p.setValeurEnCoursAsObject(p.getValeurUniqueAsObject)
            Next
            'Création des relations entre les paramètres déclinés et la table de travail
            CType(_univers, UniversOMANE).ParamRelations(parametres_decl, _tble_travail)

        End Sub
        Public Sub calcule(ByVal isScenarioCentral As Boolean)

            'Le tableau PrimesParCSR contient, pour chaque segment, les informations suivantes :
            '   - 1ere colonne : les CSR (indice 0)
            '   - 2eme colonne : la prime pure (indice 1)
            '   - 3eme colonne : la prime technique (indice 2)
            Dim PrimesParCSR(_tble_travail.Rows.Count - 1, 2)
            Dim parametres_decl As Hashtable = _coll_param.getParamDecl
            Dim parametres_uniq As Hashtable = _coll_param.getParamUniq
            Dim ageSous_Actu As Double, nbPer As Double, txNomPer As Double, txMort_Actu As Double
            Dim sommeCSR As Double = 0, CI As Double = 1, PPures() As Double, numSegment As Integer = 0
            Dim PPSegment As Double, PPureDC As Double, PPureINCINV As Double

            If isScenarioCentral Then calculeTableTravailAjouteColonnes()

            For Each r As DataRow In _tble_travail.Rows

                'Mise à jour des valeurs en cours des paramètres déclinés (y compris sensibilités)
                For Each p As IParamV2 In parametres_decl.Values
                    p.setValeurEnCoursAsObject(r.GetChildRows("relParam" & p.nom)(0)(p.nom))
                Next

                'Mise à jour des paramètres nécessaires au calcul de l'échéancier
                sommeCSR = sommeCSR + r(nomSumCSR)
                txMort_Actu = _coll_param.TxMort_Actu.getValeurEnCours
                ageSous_Actu = rechercheVdoubleMin(IIf(r(nomSexeAssu) = "H", _tble_mortalite_H, _table_mortalite_F), _
                                                   _coll_param.TxMort_Actu.getValeurEnCours, _
                                                   nomTxMortAn, _
                                                   nomAgeAnEntier)
                nbPer = CType(_coll_param.Duree_Actu.getValeurEnCours, Integer)
                txNomPer = (1 + Math.Round(_coll_param.TxNom_Actu.getValeurEnCours, 4)) ^ (1 / 12) - 1

                'Calcul des primes pures DC et INC/INV
                PPures = PP_DC_INCINV_OutilsNA(nbPer, txNomPer, CI, ageSous_Actu, r("sexe_assu"))
                PPureDC = PPures(0)
                If r("id_option") = "DC/PTIA" Then
                    PPureINCINV = 0
                Else
                    PPureINCINV = PPures(1)
                End If

                'Calcul de la prime pure du segment
                PPSegment = PPureDC * 12 _
                * (1 + _coll_param.Tx_PrixGarantiePTIA.getValeurEnCours) _
                + PPureINCINV * 12 _
                * (1 + _coll_param.Tx_chgtSecuINCINV.getValeurEnCours) _
                * (1 - _coll_param.Tx_abat_MalaNonObje.getValeurEnCours) _
                * (1 - _coll_param.Tx_abat_ExclPerteRev.getValeurEnCours)


                'Calcul des primes technique DC et INC/INV
                Dim Adc, Bdc, PtechDC, Aincinv, Bincinv, PtechINCINV As Double
                Adc = -(r(nomPourDC_Derog_Actu) * r(nomPComDC_Derog_Actu) _
                        + (1 - r(nomPourDC_Derog_Actu)) * r(nomPComDC_Non_Derog_Actu))
                Bdc = -(1 - _coll_param.Tx_fraiGestA.getValeurEnCours) * Adc
                PtechDC = _coll_param.Tx_CommiContA.getValeurEnCours * Adc _
                          - (1 - _coll_param.Tx_fraiGestA.getValeurEnCours) * Adc

                Aincinv = -(r(nomPourINCINV_Derog_Actu) * r(nomPComINCINV_Derog_Actu) _
                            + (1 - r(nomPourINCINV_Derog_Actu)) * r(nomPComINCINV_Non_Derog_Actu)) _
                            / (1 + _coll_param.Tx_TaxeAssu.getValeurEnCours)

                Bincinv = -(1 - _coll_param.Tx_fraiGestA.getValeurEnCours) * Aincinv
                PtechINCINV = _coll_param.Tx_CommiContA.getValeurEnCours _
                              * Aincinv - (1 - _coll_param.Tx_fraiGestA.getValeurEnCours) * Aincinv

                PrimesParCSR(numSegment, 0) = r(nomSumCSR)
                PrimesParCSR(numSegment, 1) = PPSegment
                If r("id_option") = "DC/PTIA" Then
                    PrimesParCSR(numSegment, 2) = PtechDC
                Else
                    PrimesParCSR(numSegment, 2) = PtechDC + PtechINCINV
                End If

                If isScenarioCentral Then
                    r(nomTxMort_Actu) = _coll_param.TxMort_Actu.getValeurEnCours
                    r("AGESOUS_ACTU") = ageSous_Actu
                    r(nomDuree_Actu) = nbPer
                    r(nomTxNom_Actu) = _coll_param.TxNom_Actu.getValeurEnCours
                    r(nomAge_FinDC) = _coll_param.Age_FinDC.getValeurEnCours
                    r(nomAge_FinINCINV) = _coll_param.Age_FinINCINV.getValeurEnCours
                    r(nomTx_mensEntreeINCINV) = _coll_param.Tx_mensEntreeINCINV.getValeurEnCours
                    r(nomTx_TechA) = _coll_param.Tx_TechA.getValeurEnCours
                    r("PP_DC") = PPures(0)
                    r("PP_INCINV") = PPureINCINV
                    r("PP_SEGMENT") = PPSegment
                    r("PTECH_SEGMENT") = PrimesParCSR(numSegment, 2)
                    r(nomTx_abat_ExclPerteRev) = _coll_param.Tx_abat_ExclPerteRev.getValeurEnCours
                    r(nomTx_abat_MalaNonObje) = _coll_param.Tx_abat_MalaNonObje.getValeurEnCours
                    r(nomTx_chgtSecuINCINV) = _coll_param.Tx_chgtSecuINCINV.getValeurEnCours
                    r(nomTx_fraiGestA) = _coll_param.Tx_fraiGestA.getValeurEnCours


                    'Remplissage des colonnes des paramètres déclinés
                    For Each p As IParamV2 In parametres_decl.Values
                        r(p.nom) = p.getValeurEnCoursAsObject
                    Next
                End If

                numSegment = numSegment + 1

            Next

            Dim pTechPf As Double = 0
            Dim pPurePf As Double = 0
            Dim poidsCSR As Double = 0
            For i As Integer = 0 To numSegment - 1
                poidsCSR = PrimesParCSR(i, 0) / sommeCSR
                pPurePf = pPurePf + PrimesParCSR(i, 1) * poidsCSR
                pTechPf = pTechPf + PrimesParCSR(i, 2) * poidsCSR
            Next

            If isScenarioCentral Then
                For Each r As DataRow In _tble_travail.Rows
                    'On ajoute une colonne poids à chaque segment du portefeuille
                    r("POIDS_CSR") = r(nomSumCSR) / sommeCSR
                    'pTechPf = pTechPf + r("PTECH_SEGMENT") * r("POIDS_CSR")
                    'pPurePf = pPurePf + r("PP_SEGMENT") * r("POIDS_CSR")
                Next
            End If

            _resultatsCalcul.PPurePf = pPurePf
            _resultatsCalcul.PTechPf = pTechPf
            _resultatsCalcul.sommeCSR = sommeCSR

        End Sub
        Public Sub calculeCloture()
            Dim parametres_decl As Hashtable = _coll_param.getParamDecl
            'Suppression des relations créées suite à la détermination des paramètres non uniques
            CType(_univers, UniversOMANE).SupprParamRelations(parametres_decl)
        End Sub

#Region "Fonctions privées intervenant dans les calculs"
        Private Function PP_DC_INCINV_OutilsNA(ByVal nbPer As Integer, ByVal txNomPer As Double, _
        ByVal CI As Double, ByVal ageSous As Integer, ByVal sexeAssu As String) As Double()

            'Calcul de la prime pure DC - Pour que l'outil soit plus rapide, on raisonne sur des tableaux
            'et non pas sur des objets
            'Le tableau contient une ligne par période -> dans la 1ere version, le raisonnement
            'est fait sur du mensuel
            'L'échéancier se présente de la façon suivante :
            '   - Colonne 0 : le CRD de la (i+1)ème période (le tableau commence à l'indice 0)
            '   - Colonne 1 : l'age de l'assuré en début de période
            '   - Colonne 2 : le taux de mortalité mensuel de la période (s'il s'agit d'un homme ou d'une femme)
            '   - Colonne 3 : la probabilité de survie dans le crédit jusqu'au début de la période
            '   - Colonne 4 : la valeur probable de la prestation
            '   - Colonne 5 : la valeur actuelle probable de la prestation DC
            '   - Colonne 6 : la valeur actuelle probable de l'assiette de prime
            '   - Colonne 7 : la valeur actuelle probable de la prestation probable en INC/INV

            Dim echeancier(nbPer - 1, 7) As Double
            Dim VAP_deces As Double = 0, VAP_INCINV As Double = 0, VAP_assiette As Double = 0
            Dim mensualite As Double = (-1) * Microsoft.VisualBasic.Pmt(txNomPer, nbPer, CI, , DueDate.EndOfPeriod)
            Dim txTechA As Double = _coll_param.Tx_TechA.getValeurEnCours

            'Initialisation de l'échéancier
            echeancier(0, 0) = CI
            echeancier(0, 1) = ageSous
            'Remarque1 : Attention au calcul des taux mensuels dans l'outil NA
            'Remarque2 : Attention au calcul des âges dans l'outil NA

            echeancier(0, 2) = IIf(sexeAssu = "H", _tble_mortalite_H, _table_mortalite_F).Rows(ageSous)(nomTxMortAn) / 12

            echeancier(0, 3) = 1
            echeancier(0, 4) = (echeancier(0, 0) * echeancier(0, 2) * echeancier(0, 3))
            echeancier(0, 5) = CI * echeancier(0, 2) * echeancier(0, 3) _
                               * (1 + txTechA) ^ (-(0.5) / 12)
            echeancier(0, 6) = CI * (1 + txTechA) ^ (-(0.5) / 12)
            echeancier(0, 7) = 0

            VAP_deces = echeancier(0, 5)
            VAP_assiette = echeancier(0, 6)

            'Récurrence sur l'échéancier
            For i = 1 To nbPer - 1
                echeancier(i, 0) = CI * ((1 + txNomPer) ^ nbPer - (1 + txNomPer) ^ i) / ((1 + txNomPer) ^ nbPer - 1)
                echeancier(i, 1) = ageSous + CType(i / 12, Integer)
                echeancier(i, 2) = (IIf(sexeAssu = "H", _tble_mortalite_H, _table_mortalite_F).Rows(ageSous + CType((i / 12) + 0.000000001, Integer))((nomTxMortAn))) / 12
                echeancier(i, 3) = echeancier(i - 1, 3) * (1 - echeancier(i, 2))
                'Attention, l'actualisation de la valeur probable des prestations DC
                's'effectue en taux proportionnel (tx_annuel/12). Ce n'est pas cohérent avec le calcul des CRD
                'Hypothèse de paiement des sinistres en milieu de période
                echeancier(i, 4) = (echeancier(i, 0) * echeancier(i, 2) * echeancier(i, 3))
                echeancier(i, 5) = (echeancier(i, 0) * echeancier(i, 2) * echeancier(i, 3)) * (1 + txTechA) ^ (-(i + 0.5) / 12)
                echeancier(i, 6) = CI * echeancier(i, 3) * (1 + txTechA) ^ (-(i + 0.5) / 12)
                'Prestation probable en INCINV (dans la version 1, on fixe la franchise à 3 mois)
                If i <= 3 Then
                    echeancier(i, 7) = 0
                Else
                    'On calcule, de même que dans le fichier de recette, durée-numPériode
                    Dim dureeCouvINC As Integer = Math.Min(36, nbPer - i)
                    Dim tx_HorsFra As Double = _TbleINCINVTaux.Rows(dureeCouvINC - 1)(If(ageSous <= 64, ageSous, 64) - 17)
                    'On récupère le taux d'entrée (ici 0,5 pour simplifier)
                    Dim tx_entree As Double = _coll_param.Tx_mensEntreeINCINV.getValeurEnCours '
                    'On applique un taux constant car la franchise est fixée à 3 mois
                    Dim tx_reducFRA As Double = _TbleINCINVFra.Rows(3)(If(ageSous <= 64, ageSous, 64) - 17)
                    'On mpultiplie par la proba de survie dans le crédit
                    echeancier(i, 7) = (tx_entree * mensualite * tx_HorsFra * tx_reducFRA * echeancier(i, 3)) * (1 + txTechA) ^ (-(i + 0.5) / 12)

                End If
                VAP_deces = VAP_deces + echeancier(i, 5)
                VAP_assiette = VAP_assiette + echeancier(i, 6)
                VAP_INCINV = VAP_INCINV + echeancier(i, 7)
            Next

            Dim result(1) As Double
            result(0) = VAP_deces / VAP_assiette
            result(1) = VAP_INCINV / VAP_assiette

            Return result

        End Function
        Private Sub calculeTableTravailAjouteColonnes()
            'Ajout à la table de travail des colonnes nécessaires au moteur de calcul
            With _tble_travail.Columns
                If Not .Contains(nomDuree_Actu) Then .Add(nomDuree_Actu, GetType(Double))
                If Not .Contains(nomTxNom_Actu) Then .Add(nomTxNom_Actu, GetType(Double))
                If Not .Contains(nomTxMort_Actu) Then .Add(nomTxMort_Actu, GetType(Double))
                If Not .Contains(nomAge_FinDC) Then .Add(nomAge_FinDC, GetType(Integer))
                If Not .Contains(nomAge_FinINCINV) Then .Add(nomAge_FinINCINV, GetType(Integer))
                If Not .Contains(nomTx_mensEntreeINCINV) Then .Add(nomTx_mensEntreeINCINV, GetType(Double))
                If Not .Contains(nomTx_TechA) Then .Add(nomTx_TechA, GetType(Double))
                If Not .Contains(nomTx_abat_ExclPerteRev) Then .Add(nomTx_abat_ExclPerteRev, GetType(Double))
                If Not .Contains(nomTx_abat_MalaNonObje) Then .Add(nomTx_abat_MalaNonObje, GetType(Double))
                If Not .Contains(nomTx_chgtSecuINCINV) Then .Add(nomTx_chgtSecuINCINV, GetType(Double))
                If Not .Contains(nomTx_fraiGestA) Then .Add(nomTx_fraiGestA, GetType(Double))

                If Not .Contains("PP_DC") Then .Add("PP_DC", GetType(Double))
                If Not .Contains("PP_INCINV") Then .Add("PP_INCINV", GetType(Double))
                If Not .Contains("AGESOUS_ACTU") Then .Add("AGESOUS_ACTU", GetType(Double))
                If Not .Contains("PP_SEGMENT") Then .Add("PP_SEGMENT", GetType(Double))
                If Not .Contains("PTECH_SEGMENT") Then .Add("PTECH_SEGMENT", GetType(Double))
                If Not .Contains("POIDS_CSR") Then .Add("POIDS_CSR", GetType(Double))
            End With
        End Sub
#End Region

#End Region

#Region "Notifications / Actualisations"
        Public Overrides Function actualise(ByVal sender As Object, ByVal notification As Object) As PTIC_Util.resultatValidationContraintes
            MyBase.actualise(sender, notification)
            If TypeOf sender Is IFonctionCalcul Then
                Dim notif As gestionCalculs.FonctionCalcul.notification = notification
                If sender Is _scenarioCentral Then
                    If notif = FonctionCalcul.notification.ApresModifEtatCalcul Then notifieChangement(Me, Moteur_Methode1.notification.etatCalculScenCentralModif)
                End If
                If sender Is simulations Then
                    If notif = FonctionCalcul.notification.ApresModifEtatCalcul Then notifieChangement(Me, Moteur_Methode1.notification.etatCalculSimulationsModif)
                End If
            End If
            If TypeOf sender Is IParamV2 Then
                _scenarioCentral.Invalider()
            End If
            Return Nothing
        End Function
        Public Sub traitEntree_EtatAChange(ByVal sender As Object, ByVal e As Traitement.notifTraitement)
            If e.Changement = Traitement.notifTraitement.natureChangement.etatCalculDataTableAchange Then
                If CType(sender, RequeteBDD).etatExecDataTable = valueEtatCalcul.A_MAJ Then
                    Me._scenarioCentral.Invalider()
                End If
            End If
        End Sub
        Public Enum notification
            etatCalculScenCentralModif
            etatCalculSimulationsModif
        End Enum
#End Region

    End Class
#End Region

End Namespace
